package be.ipl.pigolo.usecasesimpl;

import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

import javax.ejb.EJB;
import javax.ejb.Lock;
import javax.ejb.LockType;
import javax.ejb.Stateless;

import be.ipl.pigolo.dao.FermierDao;
import be.ipl.pigolo.dao.PartieDao;
import be.ipl.pigolo.dao.PartieFermierDao;
import be.ipl.pigolo.domaine.Cochon;
import be.ipl.pigolo.domaine.Fermier;
import be.ipl.pigolo.domaine.Fermier.STATUS_CONNEXION;
import be.ipl.pigolo.domaine.Partie;
import be.ipl.pigolo.domaine.Partie.Etat;
import be.ipl.pigolo.domaine.PartieFermier;
import be.ipl.pigolo.usecases.GestionPartie;
import be.ipl.pigolo.util.GestionFichier;
import be.ipl.pigolo.util.GestionFichierImpl;
import be.ipl.pigolo.util.Util;

@Stateless
public class GestionPartieImpl implements GestionPartie {

	@EJB
	private PartieDao partiedao;

	@EJB
	private FermierDao fermierdao;

	@EJB
	private PartieFermierDao partieFermierdao;

	@Override
	public boolean inscrire(String nom, String motdepasse) {
		if (Util.checkNullEmpty(nom))
			return false;
		if (Util.checkNullEmpty(motdepasse))
			return false;
		Fermier fermier = new Fermier(nom, motdepasse);
		return (fermierdao.enregistrer(fermier) == null ? false : true);
	}

	@Override
	public boolean connexion(String nom, String motdepasse) {
		if (Util.checkNullEmpty(nom))
			return false;
		if (Util.checkNullEmpty(motdepasse))
			return false;

		Fermier fermier = fermierdao.rechercher(nom);
		if (Util.checkNull(fermier))
			return false;
		if (!fermier.getMotDePasse().equals(motdepasse))
			return false;
		fermier.setStatusConnexion(STATUS_CONNEXION.CONNECTE);
		return (fermierdao.connexion(fermier) == null ? false : true);
	}

	@Override
	public boolean creerPartie(String nomPartie, int timerTour) {
		// Test si le nom est null ou vide
		if (Util.checkNullEmpty(nomPartie))
			return false;
		// Test si le nom est de bonne longueur et les caractères correctes
		if (!Util.checkRegexString(nomPartie, Util.REGEX_LENGTH_CHAR))
			return false;

		Partie partie = partiedao.rechercher(nomPartie);
		// Test si la partie est déjà initialisé
		if (!Util.checkNull(partie))
			return false;
		this.partiedao.creerPartie(new Partie(nomPartie, timerTour));
		return true;
	}

	@Override
	public boolean rejoindrePartie(String nomPartie, String nomFermier) {
		// Test si le nom est null ou vide
		if (Util.checkNullEmpty(nomPartie))
			return false;
		// Test si le nom est null ou vide
		if (Util.checkNullEmpty(nomFermier))
			return false;

		Partie partie = this.partiedao.rechercher(nomPartie);
		// Test si la partie est crée
		if (Util.checkNull(partie)) {
			return false;
		}
		// Test si l'état est correcte
		if (partie.getEtat() != Etat.EN_ATTENTE)
			return false;

		// Test si le joueur est déjà dans une partie
		if (partie.getFermier(nomFermier) != null) {
			return false;
		}
		// partie = this.partiedao.rechercher(partie.getId());
		Fermier fermier = this.fermierdao.rechercher(nomFermier);
		boolean resultat = partie.ajouterFermier(new PartieFermier(fermier));

		// MET A JOUR TOUTES LES INFORMATIONS
		miseAJourData(partie);

		return resultat;
	}

	@Override
	@Lock(LockType.READ)
	public List<PartieFermier> listerLesParticipants(String partie) {
		if (Util.checkNullEmpty(partie))
			return null;
		Partie laPartie = partiedao.rechercher(partie);
		if (Util.checkNull(laPartie))
			return null;
		return laPartie.getFermiers();
	}

	@Override
	@Lock(LockType.READ)
	public List<Partie> listerLesParties() {
		return this.partiedao.listerPartiesEnAttentes();
	}

	@Override
	public boolean prendreCochon(int id_cochon, String nomPartie,
			String nomFermier) {
		// Test si le nom est null ou vide
		if (Util.checkNullEmpty(nomFermier))
			return false;
		if (Util.checkNullEmpty(nomPartie))
			return false;

		Partie partie = this.partiedao.rechercher(nomPartie);
		if (partie == null)
			return false;
		PartieFermier partieFermier = partie.getFermier(nomFermier);
		if (partieFermier != null) {
			Cochon tabCochon[][] = partie.getTableauDesCochons();

			for (int i = 0; i < tabCochon.length; i++) {
				for (int j = 0; j < tabCochon[i].length; j++) {
					if (tabCochon[i][j] != null
							&& tabCochon[i][j].getId() == id_cochon) {
						boolean resultatPrendreCochon = partie.prendreUnCochon(
								tabCochon[i][j], partieFermier);

						// MET A JOUR TOUTES LES INFORMATIONS
						miseAJourData(partie);

						return resultatPrendreCochon;
					}
				}
			}
		}

		// MET A JOUR TOUTES LES INFORMATIONS
		miseAJourData(partie);
		return false;
	}

	@Override
	public boolean quitter(String nomPartie) {
		// Test si le nom de la partie n'est pas correcte
		if (Util.checkNullEmpty(nomPartie))
			return false;
		Partie partie = this.partiedao.rechercher(nomPartie);
		if (Util.checkNull(partie))
			return false;
		// Test si la partie n'est pas en cours
		if (partie.getEtat() != Etat.EN_COURS)
			return false;
		return partie.finDePartie();
	}

	@Override
	public boolean annuler(String nomPartie) {
		// Test si le nom de la partie n'est pas correcte
		if (Util.checkNullEmpty(nomPartie))
			return false;
		Partie partie = this.partiedao.rechercher(nomPartie);
		List<PartieFermier> list = this.listerLesParticipants(nomPartie);
		// Test si la partie n'est pas en cours
		if (partie.getEtat() != Etat.EN_ATTENTE)
			return false;
		boolean result = partie.annulerPartie(partie);
		for (int i = 0; i < list.size(); i++) {
			Fermier ferm = list.get(i).getFermier();
			this.fermierdao.connexion(ferm);
		}
		return result;
	}

	@Override
	public String journal(String nomPartie) {
		if (Util.checkNullEmpty(nomPartie))
			return "<ERROR : Nom>";
		Partie partie = partiedao.rechercher(nomPartie);
		if (Util.checkNull(partie))
			return "<ERROR : Partie>";
		GestionFichier gestFichier = new GestionFichierImpl(partie.getId());
		return gestFichier.lireUnFichier();
	}

	@Override
	@Lock(LockType.READ)
	public List<Partie> listerToutesLesParties() {
		return partiedao.listerToutesParties();
	}

	@Override
	public String getEtat(String nomPartie) {
		// Test si le nom de la partie n'est pas correcte
		if (Util.checkNullEmpty(nomPartie))
			return "Une erreur est survenue!!";
		Partie partie = this.partiedao.rechercher(nomPartie);
		return partie.getEtat().name();
	}

	@Override
	public boolean deconnexion(String nomFermier) {
		if (Util.checkNullEmpty(nomFermier))
			return false;
		Fermier fermier = fermierdao.rechercher(nomFermier);
		if (Util.checkNull(fermier))
			return false;
		fermier.setStatusConnexion(STATUS_CONNEXION.DECONNECTE);
		return (fermierdao.connexion(fermier) == null ? false : true);
	}

	@Override
	public Partie commencerPartie(String nom) {
		if (Util.checkNullEmpty(nom))
			return null;
		Partie p = partiedao.rechercher(nom);
		if (p == null)
			return null;
		if (p.commencerPartie()) {
			// TODO prévoir exception
			commencerTourSuivant(p.getNom());
			return p;
		}
		return null;
	}

	private boolean commencerTourSuivant(String nomDeLaPartie) {
		final String nomPartie = nomDeLaPartie;
		Partie partie = partiedao.rechercher(nomPartie);

		if (!partie.commencerTourSuivant()) {
			// MET A JOUR TOUTES LES INFORMATIONS
			miseAJourData(partie);
			return false;
		}

		// MET A JOUR TOUTES LES INFORMATIONS
		miseAJourData(partie);

		// Lancer timer pour prendre les cochons
		new Timer(partie.getNom() + "_timer_tour").schedule(new TimerTask() {

			@Override
			public void run() {
				Partie partie = partiedao.rechercher(nomPartie);

				partie.enleverPurinsCochons();

				// MET A JOUR TOUTES LES INFORMATIONS
				miseAJourData(partie);

				// Lancer timer entre les tours
				new Timer(partie.getNom() + "_timer_entre_tour").schedule(
						new TimerTask() {

							@Override
							public void run() {

								commencerTourSuivant(nomPartie);

							}
						}, partie.getTimerEntreTour() * 1000);
			}

		}, partie.getTimerTour() * 1000);
		return true;
	}

	private void miseAJourData(Partie partie) {
		partiedao.mettreAJour(partie);
		for (PartieFermier pf : partie.getFermiers()) {
			partieFermierdao.mettreAJour(pf);
			fermierdao.mettreAJour(pf.getFermier());
		}
	}

	@Override
	public Partie rechercherPartie(String nom) {
		Partie p = partiedao.rechercher(nom);
		return p;
	}

}
